package com.jiamingZhao.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Data;
import lombok.Getter;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author ：JiaMing Zhao
 * @since ：2025/6/5 14:51
 */
@Data
public class DataSourceConfig {
    private static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";

    private static final String JDBC_DRIVER_P6SPY = "com.p6spy.engine.spy.P6SpyDriver";

    private static final String DB_URL = "jdbc:p6spy:mysql://192.168.100.150/zhiyi_bladex?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true";

    private static final String USER = "iipmes";

    private static final String PASSWORD = "iipmes2020";

    private static final DataSource dataSource;

    public static DataSource getHikariDataSource() {
        return dataSource;
    }

    static {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(DB_URL);
        config.setUsername(USER);
        config.setPassword(PASSWORD);
        config.setDriverClassName(JDBC_DRIVER_P6SPY);

        // 连接池配置
        config.setMaximumPoolSize(20);       // 最大连接数
        config.setMinimumIdle(5);            // 最小空闲连接
        config.setIdleTimeout(600000);       // 空闲连接超时时间(ms)
        config.setConnectionTimeout(30000);   // 连接获取超时时间(ms)
        config.setMaxLifetime(1800000);       // 连接最大存活时间(ms)
        config.setAutoCommit(true);           // 自动提交

        // MySQL优化配置
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        config.addDataSourceProperty("useServerPrepStmts", "true");

        dataSource = new HikariDataSource(config);
    }


    /**
     * 获取数据库连接
     */
    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 安全关闭连接（实际将连接返回到连接池）
     */
    public static void closeConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close(); // 对于连接池，实际上是归还连接
            } catch (SQLException e) {
                System.err.println("关闭数据库连接时出错: " + e.getMessage());
            }
        }
    }

    /**
     * 带事务管理的模板方法
     */
    public static <T> T executeWithTransaction(ConnectionFunction<T> function) {
        Connection conn = null;
        try {
            conn = getConnection();
            conn.setAutoCommit(false);

            T result = function.apply(conn);
            conn.commit();
            return result;
        } catch (SQLException e) {
            try {
                conn.rollback();
            } catch (SQLException ex) {
                System.err.println("回滚事务失败: " + ex.getMessage());
            }
            throw new RuntimeException("数据库操作失败", e);
        } finally {
            closeConnection(conn);
        }
    }


    @FunctionalInterface
    public interface ConnectionFunction<T> {
        T apply(Connection connection) throws SQLException;
    }

}
